// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "framework.h"
#include <string>
#include <Shlwapi.h>
#pragma comment(lib,"Shlwapi.lib")

#define EXENAME "RecvCash"
#define WxReciveMessage 0x3C9292			//接收消息 1 2	
#define WxReciveMessageCall 0x85A30			//接收消息 1 2 	  	
#define MsgContentOffset 0x68			//消息内容的偏移 1 2
#define WxidOffset 0x40					//微信ID/群ID偏移 1 2	

using namespace std;

void InitWindow(HMODULE hModule);
void HookMsgAddr();
void RecieveWxMesage();
void __stdcall SendWxMessage(DWORD r_eax);

DWORD RetkReciveMsgAddr = (DWORD)GetModuleHandle(TEXT("WeChatWin.dll")) + WxReciveMessage + 5;
DWORD OverReciveMsgCallAddr = (DWORD)GetModuleHandle(TEXT("WeChatWin.dll")) + WxReciveMessageCall;

BOOL APIENTRY DllMain(HMODULE hModule,
	DWORD  ul_reason_for_call,
	LPVOID lpReserved
)
{
	switch (ul_reason_for_call)
	{
	case DLL_PROCESS_ATTACH:
	{
		CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)InitWindow, hModule, 0, NULL);
	}
	case DLL_THREAD_ATTACH:
	case DLL_THREAD_DETACH:
	case DLL_PROCESS_DETACH:
		break;
	}
	return TRUE;
}

//hook消息处理
void HookMsgAddr() {
	DWORD dwHookAddr = (DWORD)GetModuleHandle(TEXT("WeChatWin.dll")) + WxReciveMessage;
	//组装跳转数据
	BYTE jmpCode[5] = { 0 };
	jmpCode[0] = 0xE9;

	//计算偏移
	*(DWORD*)& jmpCode[1] = (DWORD)RecieveWxMesage - dwHookAddr - 5;

	// 保存以前的属性用于还原
	DWORD OldProtext = 0;

	// 因为要往代码段写入数据，又因为代码段是不可写的，所以需要修改属性
	VirtualProtect((LPVOID)dwHookAddr, 5, PAGE_EXECUTE_READWRITE, &OldProtext);

	//写入自己的代码
	memcpy((void*)dwHookAddr, jmpCode, 5);

	// 执行完了操作之后需要进行还原
	VirtualProtect((LPVOID)dwHookAddr, 5, OldProtext, &OldProtext);
}
//初始化窗口
void InitWindow(HMODULE hModule)
{
	HookMsgAddr();
}

__declspec(naked) void RecieveWxMesage()
{
	//保存现场
	__asm
	{
		pushad;
		push eax;
		call SendWxMessage;
		popad;
		//调用被覆盖的call
		call OverReciveMsgCallAddr;
		//跳转到返回地址
		jmp RetkReciveMsgAddr;
	}
}

//将获取到的消息发送给显示端
void __stdcall SendWxMessage(DWORD r_eax) {
	HWND hWnd = FindWindow(NULL, TEXT(EXENAME));
	if (NULL == hWnd) {
		hWnd = FindWindow(TEXT(EXENAME), NULL);
	}
	if (NULL == hWnd) {
		return;
	}
	
	LPVOID pWxid = *((LPVOID *)(r_eax + WxidOffset));
	if ((StrCmpW((wchar_t*)pWxid, L"gh_3dfda90e39d6") == 0) || (StrCmpW((wchar_t*)pWxid, L"gh_f0a92aa7146c") == 0)) {
		LPVOID pContent = *((LPVOID *)(r_eax + MsgContentOffset));
		wstring content((wchar_t*)pContent);

		COPYDATASTRUCT userinfo;
		userinfo.dwData = 10000;
		userinfo.cbData = content.length() * 2 + 1;
		userinfo.lpData = (PVOID)content.c_str();
		SendMessage(hWnd, WM_COPYDATA, (WPARAM)hWnd, (LPARAM)&userinfo);
	}
}
